package com.hmdp.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.lang.UUID;
import cn.hutool.core.util.RandomUtil;
import com.baomidou.mybatisplus.extension.conditions.query.QueryChainWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.hmdp.dto.LoginFormDTO;
import com.hmdp.dto.Result;
import com.hmdp.dto.UserDTO;
import com.hmdp.entity.User;
import com.hmdp.mapper.UserMapper;
import com.hmdp.service.IUserService;
import com.hmdp.utils.RegexUtils;
import com.hmdp.utils.SendSMSUtil;
import com.hmdp.utils.UserHolder;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.connection.BitFieldSubCommands;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.web.bind.annotation.RequestParam;

import javax.annotation.Resource;
import javax.servlet.http.HttpSession;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.*;
import java.util.concurrent.TimeUnit;

import static com.hmdp.utils.RedisConstants.USER_SIGN_KEY;
import static com.hmdp.utils.SystemConstants.USER_NICK_NAME_PREFIX;

/**
 * <p>
 * 服务实现类
 * </p>
 *
 * @author 虎哥
 * @since 2021-12-22
 */
@Slf4j
@Service
public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements IUserService {

    @Resource
    private StringRedisTemplate stringRedisTemplate;

    @Override
    public Result sendCode(String phone, HttpSession session) {
        if (RegexUtils.isPhoneInvalid(phone))
            return Result.fail("无效的手机号");
        String code = RandomUtil.randomNumbers(6);

        stringRedisTemplate.opsForValue().set("login:code:" + phone, code, 5, TimeUnit.MINUTES);
        log.debug("发送验证码成功，验证码为{}", code);
        /* 真实手机号验证码登录
        Map<String, String> map = SendSMSUtil.senSMSUtil(phone);
        String msg=map.get("msg");
        String code=map.get("code");
        if (msg == null || !msg.equals("OK")) {// 发送不成功
            System.out.println("失败");
            return Result.fail(msg);
        }else session.setAttribute("code",code);
         */
        return Result.ok();
    }

    @Override
    public Result login(LoginFormDTO loginForm, HttpSession session) {
        String phone = loginForm.getPhone();
        String password = loginForm.getPassword();
        String code = loginForm.getCode();
        String token = UUID.randomUUID().toString(true);
        String key = "login:token:" + token;
        if (RegexUtils.isPhoneInvalid(phone))
            return Result.fail("无效的手机号");
        if (password == null || password.isEmpty()) {
            String cacheCode = stringRedisTemplate.opsForValue().get("login:code:" + phone);
            if (code == null || !code.equals(cacheCode))
                return Result.fail("验证码错误");
            User user = query().eq("phone", phone).one();
            System.out.println(user);
            if (user == null) {
                user = new User();
                user.setPhone(phone);
                user.setCreateTime(LocalDateTime.now());
                user.setNickName(USER_NICK_NAME_PREFIX + RandomUtil.randomString(6));
                save(user);
            }
            System.out.println("user.getId():" + user.getId());
            Map<String, String> userMap = new HashMap<>();
            userMap.put("id", user.getId().toString());
            userMap.put("nickName", user.getNickName());
            userMap.put("icon", user.getIcon());
            stringRedisTemplate.opsForHash().putAll(key, userMap);
            //测试需要，先注释掉
//            stringRedisTemplate.expire(key,30,TimeUnit.MINUTES);
        } else {
            User user = query().eq("phone", phone).eq("password", password).one();
            if (user == null)
                return Result.fail("手机号或密码错误");
            Map<String, String> userMap = new HashMap<>();
            userMap.put("id", user.getId().toString());
            userMap.put("nickName", user.getNickName());
            userMap.put("icon", user.getIcon());
            stringRedisTemplate.opsForHash().putAll(key, userMap);
            stringRedisTemplate.expire(key, 30, TimeUnit.MINUTES);
        }
        return Result.ok(token);
    }

    @Override
    public Result sign() {
        Long userId = UserHolder.getUser().getId();
        LocalDateTime now = LocalDateTime.now();
        String yyyyMM = now.format(DateTimeFormatter.ofPattern(":yyyyMM"));
        String key = USER_SIGN_KEY + userId + yyyyMM;
        int dayOfMonth = now.getDayOfMonth();
        stringRedisTemplate.opsForValue().setBit(key, dayOfMonth - 1, true);
        return Result.ok();
    }

    @Override
    public Result signCount() {
        Long userId = UserHolder.getUser().getId();
        LocalDateTime now = LocalDateTime.now();
        String yyyyMM = now.format(DateTimeFormatter.ofPattern(":yyyyMM"));
        String key = USER_SIGN_KEY + userId + yyyyMM;
        int dayOfMonth = now.getDayOfMonth();
        List<Long> result = stringRedisTemplate.opsForValue().bitField(
                key, BitFieldSubCommands.create().
                        get(BitFieldSubCommands.BitFieldType.unsigned(dayOfMonth)).valueAt(0)
        );
        if (result == null || result.isEmpty()) {
            return Result.ok(0);
        }
        Long l = result.get(0);
        if (l == null || l == 0) {
            return Result.ok(0);
        }
        int count = 0;
        while ((l & 1) != 0) {
            count++;
            l >>>= 1;
        }
        return Result.ok(count);
    }
}
